﻿using CommandLine;
using ExcelDataReader;
using System.Data;
using System.Text;

namespace ExcelToJson
{
    public sealed class Program
    {
        public static Options? CurOption { set; get; } = default;

        private static void Main(string[] args)
        {
            //.net core支持的enconding非常少, 需要用Codepages来解决.
            //https://stackoverflow.com/questions/50858209/system-notsupportedexception-no-data-is-available-for-encoding-1252
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            WriteLineColor("Begin to convert", ConsoleColor.Blue);

            try
            {
                Parser.Default.ParseArguments<Options>(args).WithParsed(Run).WithNotParsed((IEnumerable<Error> errors) =>
                {
                    var sb = new StringBuilder();
                    foreach (var error in errors)
                    {
                        sb.AppendLine(sb.ToString());
                    }
                    WriteLineColor(sb.ToString(), ConsoleColor.Red);
                });
            }
            catch (Exception exp)
            {
                WriteLineColor(exp.ToString(), ConsoleColor.Red);
            }
        }

        /// <summary>
        /// 根据命令行参数，执行Excel数据导出工作
        /// </summary>
        /// <param name="options">命令行参数</param>
        private static void Run(Options options)
        {
            CurOption = options;
            if (options.ExcelPath == null || options.ExcelPath.Count() == 0)
            {
                throw new Exception("No excel files.");
            }

            //用于产生string到
            List<string> typeMapperList = new List<string>();

            foreach (string curExcelFileName in options.ExcelPath)
            {
                try
                {
                    if (string.IsNullOrEmpty(curExcelFileName))//文件名为空，跳过
                    {
                        continue;
                    }

                    // 加载Excel文件
                    using (FileStream curExcelFile = File.Open(curExcelFileName, FileMode.Open, FileAccess.Read))
                    {
                        // Reading from a OpenXml Excel file (2007 format; *.xlsx)
                        IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(curExcelFile);

                        // The result of each spreadsheet will be created in the result.Tables
                        DataSet book = excelReader.AsDataSet();

                        //-- 确定编码
                        Encoding encoding = new UTF8Encoding(false);
                        if (options.Encoding != "utf8-nobom")
                        {
                            foreach (EncodingInfo ei in Encoding.GetEncodings())
                            {
                                Encoding e = ei.GetEncoding();
                                if (e.EncodingName == options.Encoding)
                                {
                                    encoding = e;
                                    break;
                                }
                            }
                        }

                        //检查sheet个数
                        if (book.Tables.Count < 1)
                        {
                            throw new Exception("Excel文件中没有找到Sheet: " + curExcelFile);
                        }

                        //取出sheet
                        foreach (DataTable sheet in book.Tables)
                        {
                            string sheetName = sheet.TableName;
                            bool isContainChinese = System.Text.RegularExpressions.Regex.IsMatch(sheetName, @"[\u4e00-\u9fa5]");

                            if (isContainChinese)//如果Sheet是中文名，则跳过
                            {
                                continue;
                            }

                            //检查sheet是否为空
                            if (sheet.Rows.Count <= 0)
                            {
                                throw new Exception("Excel Sheet中没有数据: " + curExcelFileName);
                            }

                            //-- 导出JSON文件
                            if (!string.IsNullOrEmpty(options.JsonPath))
                            {
                                JsonGenerator exporter = new JsonGenerator(sheet, options.HeaderRows, options.Lowcase);
                                exporter.SaveToFile(Path.Combine(options.JsonPath, sheetName, ".json"), encoding);
                            }

                            //-- 生成C#定义文件
                            if (!string.IsNullOrEmpty(options.CSharpPath))
                            {
                                CSDefineGenerator exporter = new CSDefineGenerator(sheet, options.HeaderRows, options.Platform);

                                exporter.ClassComment = string.Format("// Generate From {0}", curExcelFileName
                                     + ". SheetName: " + sheetName);

                                string cSharpOutPath = Path.Combine(options.CSharpPath, sheetName, ".cs");
                                exporter.SaveToFile(cSharpOutPath, encoding);
                                typeMapperList.Add(sheetName);
                            }

                            //生成java定义文件
                            if (!string.IsNullOrEmpty(options.JavaPath) && !string.IsNullOrEmpty(options.JavaPackage))
                            {
                                string excelName = Path.GetFileName(curExcelFileName);
                                JavaDefineGenerator exporter = new JavaDefineGenerator(sheet);

                                exporter.ClassComment = string.Format("// Generate From {0}", curExcelFileName
                                     + ". SheetName: " + sheetName);

                                string javaOutPath = options.JavaPath + sheetName + ".java";
                                exporter.SaveToFile(options.JavaPackage, options.javaImport, javaOutPath, encoding);
                            }
                        }
                    }
                }
                catch (Exception exp)
                {
                    WriteLineColor(exp.ToString(), ConsoleColor.Red);
                }
            }

            //-- 生成C#的映射文件
            if (!string.IsNullOrEmpty(options.CSharpPath))
            {
                string mapFilePath = options.CSharpPath + "ConfigMapper.cs";
                CSMapperGenerator.SaveMapFile(typeMapperList, mapFilePath, new UTF8Encoding(false));
            }
        }//Run

        /// <summary>
        /// 在console打印带颜色的log
        /// </summary>
        /// <param name="str"></param>
        /// <param name="color"></param>
        public static void WriteLineColor(string str, ConsoleColor color)
        {
            ConsoleColor currentForeColor = Console.ForegroundColor;
            Console.ForegroundColor = color;
            Console.WriteLine(str);
            Console.ForegroundColor = currentForeColor;
        }
    }
}